import 'builder.dart';
import 'compute.dart';
import 'helpers/effect.dart';
import 'helpers/render.dart';
import 'helpers/tools.dart';
import 'helpers/update.dart';
import 'watch.dart';

/// [Ref]是一个Map类型的响应式数据
class Ref<T> {
  late T _data;
  // widget缓存
  List<StreamCollectFactory> _streamCache = [];
  // watch对象缓存
  List<WatchCollectFactory> _watchCache = [];
  // compute对象缓存
  List<ComputeComputeFactory> _computeCache = [];

  Ref(T data) {
    this._data = data;
  }

  /// 传入一个Ref数组, 更新所有关联的Widget
  ///
  /// [handler] 更新函数，里面可以收集所有的被读取和被修改的响应式对象都将被收集并执行更新操作
  ///
  /// [options] 可选
  ///
  /// 如果返回false，不会触发依赖的widget更新.
  static update(handler(), [UpdateOptions? options]) {
    globalRefUpdateInstance = Update();
    var _handerResult = handler();
    List<Ref> _updateRefs = (globalRefUpdateInstance as Update).refs;
    globalRefUpdateInstance = null;
    if (options != null && options.refs != null) {
      _updateRefs = (options.refs as List<Ref>);
    }
    if (_handerResult != false && _updateRefs.length > 0) {
      //  && (_updateRefs[0] is Ref || _updateRefs[0] is RefCompute)
      _updateRefs[0]._runEffect(_updateRefs, options);
      _updateRefs[0]._runRender(_updateRefs, options);
    }
  }

  // 单独运行副作用
  _runEffect(List<Ref> currentList, [UpdateOptions? options]) {
    List<WatchCollectFactory> _tempWatchList = [];
    List<ComputeComputeFactory> _tempComputeList = [];
    currentList.forEach((ele) {
      _tempWatchList.addAll(ele._watchCache);
      _tempComputeList.addAll(ele._computeCache);
    });
    excuteEffect(_tempWatchList, options);
    excuteEffect(_tempComputeList, options);
  }

  // 单独运行widget更新
  _runRender(List<Ref> currentList, [UpdateOptions? options]) {
    List<StreamCollectFactory> _tempStreamCache = [];
    currentList.forEach((ele) {
      _tempStreamCache.addAll(ele._streamCache);
    });
    renderWidget(_tempStreamCache, options);
  }

  /// 数据发生改变
  _refresh() {
    if (globalRefUpdateInstance != null && globalRefUpdateInstance is Update) {
      // 为update收集依赖(收集在Ref.update中运行的Ref对象)
      (globalRefUpdateInstance as Update).collect(this);
    } else {
      // 运行副作用,widget更新
      _runEffect([this]);
      _runRender([this]);
    }
  }

  /// 修改数据，触发依赖的widget更新.
  ///
  /// [modifyier]这是一个函数，内部执行修改操作，返回一个值.
  ///
  /// 如果返回false，不会触发依赖的widget更新.
  bool _isSetValue = false;
  set(modifyier()) {
    _isSetValue = true;
    if (modifyier() == false) {
      _isSetValue = false;
      return;
    }
    _isSetValue = false;
    _refresh();
  }

  /// [data]设置值，触发全部依赖的widget更新
  set value(data) {
    try {
      data = data is Ref ? data.value : data;
      if (isBaseType(this._data) && data == this._data) return;
      this._data = data;
      if (_isSetValue != true) _refresh();
    } catch (e) {
      print('app wrong: Ref set value 赋值出错了！');
    }
  }

  /// 获取值
  T get value {
    if (globalRefBuilderInstance != null ||
        globalRefWatchInstance != null ||
        globalRefComputeInstance != null ||
        globalRefUpdateInstance != null) {
      collect();
    }
    return _data;
  }

  /// 自动收集依赖（请勿调用）
  collect() {
    if (globalRefBuilderInstance is StreamCollectFactory) {
      if (!_streamCache.contains(globalRefBuilderInstance)) {
        _streamCache.add(globalRefBuilderInstance);
      }
      if (!(globalRefBuilderInstance as StreamCollectFactory)
          .refs
          .contains(this)) {
        (globalRefBuilderInstance as StreamCollectFactory).refs.add(this);
      }
    }
    if (globalRefWatchInstance is WatchCollectFactory) {
      if (!_watchCache.contains(globalRefWatchInstance)) {
        _watchCache.add(globalRefWatchInstance);
      }
      if (!(globalRefWatchInstance as WatchCollectFactory)
          .refs
          .contains(this)) {
        (globalRefWatchInstance as WatchCollectFactory).refs.add(this);
      }
    }
    if (globalRefComputeInstance is ComputeComputeFactory) {
      if (!_computeCache.contains(globalRefComputeInstance)) {
        _computeCache.add(globalRefComputeInstance);
      }
      if (!(globalRefComputeInstance as ComputeComputeFactory)
          .refs
          .contains(this)) {
        (globalRefComputeInstance as ComputeComputeFactory).refs.add(this);
      }
    }
    if (globalRefUpdateInstance is Update) {
      // 为update收集依赖(收集在Ref.update中运行的Ref对象)
      _refresh();
    }
  }

  /// 自动清除stream缓存（请勿调用）
  dispose(dynamic instance) {
    if (instance is ComputeComputeFactory) {
      _computeCache.remove(instance);
    } else if (instance is WatchCollectFactory) {
      _watchCache.remove(instance);
    } else if (instance is StreamCollectFactory) {
      _streamCache.remove(instance);
    }
  }
}
